/**
 * Copyright (c) 2010, Todd Ginsberg
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of Todd Ginsberg, or Gowalla nor the
 *      names of any contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *  Also, please use this for Good and not Evil.  
 */
package com.ginsberg.gowalla.dto.problems;

import com.ginsberg.gowalla.dto.Category;
import com.ginsberg.gowalla.dto.GeoPoint;

/**
 * Class to help create scenario-specific ProblemReports.  There are so many jokes
 * around the name ProblemFactory it's killing me.
 * 
 * Q: Why do you create ProblemReports this way?  Why not let the user file them with 
 * just a message?
 * 
 * A: If you are an STE you know that accurate reporting is essential.  Bad or misleading 
 * reports waste time and can cause more problems than they intend to solve.  This way,
 * data is submitted in a regular, unambiguous way.  
 * 
 * @author Todd Ginsberg
 */
public abstract class ProblemFactory {

	
	/**
	 * Report the physical address for this spot.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param address The physical address of the spot.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportAddress(final int spotId, final String address, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(address == null) {
			throw new IllegalArgumentException("Provide address");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Needs address: %s", address);
		} else {
			message = String.format("Needs address: %s [%s]", address, comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
	
	/**
	 * Report that the given spot is in a bad location.  
	 * 
	 * @param spotId The id of the spot to report.
	 * @param correctLocation The location the spot should be moved to (required).
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportBadLocation(final int spotId, final GeoPoint correctLocation, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(correctLocation == null) {
			throw new IllegalArgumentException("Provide a correct location");
		}
		String message = null; 
		if(comment == null) {
			message = String.format("Correct location is %s x %s", correctLocation.getLatitude(), correctLocation.getLongitude());
		} else {
			message = String.format("Correct location is %s x %s [%s]", correctLocation.getLatitude(), correctLocation.getLongitude(), comment);
		}
		return new ProblemReport(ProblemReport.Type.MISLOCATED, spotId, message);
	}
	
	/**
	 * Report to Gowalla that the given spot should be closed.  This can either mean
	 * a business has closed or a temporary event is over.  This request means that 
	 * the spot will just disappear but will remain in user histories.  This is different 
	 * than a delete request (please see reportInvalid).
	 * 
	 * @param spotId The id of the spot to report.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */
	public static ProblemReport reportClosed(final int spotId, final String comment) {
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		String message = null;
		if(comment == null) {
			message = "Spot should be closed.";
		} else {
			message = String.format("Spot should be closed [%s]", comment);
		}
		return new ProblemReport(ProblemReport.Type.VENUE_CLOSED, spotId, message);
	}
	
	/**
	 * Flag the given spot as a duplicate of another.  When you file a report using this method,
	 * it will file against badSpotId as "This is a duplicate of [goodSpotId]".  The bad spot is generally
	 * considered to be the one that is newer, giving preference to people who created spots first.  
	 * If however, you feel that the older spot is very far off, or doesn't have as much information
	 * as a newer spot, it can be appropriate to make the newer spot the good one.  Don't abuse that.
	 * 
	 * If neither spot seems very good, consider filing a report to move one of them to the correct spot.
	 * Just pick one to be the good one, in that case.
	 * 
	 * You do not have to file reports on both spots:  X is a duplicate of Y, Y is a duplicate of X.  Gowalla's
	 * system will take care of this if they want double entry accounting (so to speak).
	 * 
	 * @param badSpotId The id of the spot considered the loser in a merge war.
	 * @param goodSpotId The id of the spot considered the winner in a merge war.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */
	public static ProblemReport reportDuplicate(final int badSpotId, final int goodSpotId, final String comment) {
		if(badSpotId == 0) {
			throw new IllegalArgumentException("Provide bad spot id.");
		}
		if(goodSpotId == 0) {
			throw new IllegalArgumentException("Provide good spot id.");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Duplicate of %d (other one is better).", goodSpotId);
		} else {
			message = String.format("Duplicate of %d (other one is better) [%s]", goodSpotId, comment);
		}
		return new ProblemReport(ProblemReport.Type.DUPLICATE, badSpotId, message);
	}
	
	/**
	 * Report to Gowalla that the given spot should be deleted.  Please only use
	 * this to report spots that are fake or inappropriate.  If a spot is deleted, it
	 * will be removed from user histories, so don't use this for spots that
	 * have just closed down.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */
	public static ProblemReport reportInvalid(final int spotId, final String comment) {
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		String message = null;
		if(comment == null) {
			message = "Spot is invalid, please delete (inapropriate, fake, etc).";
		} else {
			message = String.format("Spot is invalid, please delete  (inapropriate, fake, etc) [%s]", comment);
		}
		return new ProblemReport(ProblemReport.Type.INVALID, spotId, message);
	}
	
	/**
	 * Report that the given spot is in the wrong category. Don't use this to report Apple Stores
	 * or stores like that, use reportNeedsCustomStamp().
	 * 
	 * @param spotId The id of the spot to report.
	 * @param category The Category the spot should be (required).
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportMiscategorized(final int spotId, final Category category, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(category == null) {
			throw new IllegalArgumentException("Provide a correct category");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Correct category is %s", category.getName());
		} else {
			message = String.format("Correct category is %s [%s]", category.getName(), comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
	

	/**
	 * Report that the given spot needs custom artwork.  An example is an Apple store that is missing custom
	 * Apple art, or Chipotle, or London Underground.  Do NOT use this to file requests for local favorites
	 * that need brand new custom art.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param artworkNeeded Text description of the artwork needed (Apple, Underground, etc).
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportNeedsExistingCustomStamp(final int spotId, final String artworkNeeded, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(artworkNeeded == null) {
			throw new IllegalArgumentException("Provide what stamp it needs");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Needs custom artwork: %s", artworkNeeded);
		} else {
			message = String.format("Needs custom artwork: %s [%s]", artworkNeeded, comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
	
	/**
	 * Report the phone number for this spot.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param phone The phone number of the spot.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportPhoneNumber(final int spotId, final String phone, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(phone == null) {
			throw new IllegalArgumentException("Provide phone");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Needs phone number: %s", phone);
		} else {
			message = String.format("Needs phone number: %s [%s]", phone, comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
	
	/**
	 * Report the twitter handle for this spot.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param twitter The twitter handle that represents this spot.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportTwitterHandle(final int spotId, final String twitter, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(twitter == null) {
			throw new IllegalArgumentException("Provide twitter handle");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Needs Twitter handle: %s", twitter);
		} else {
			message = String.format("Needs Twitter handle: %s [%s]", twitter, comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
	
	/**
	 * Report the website for this spot.
	 * 
	 * @param spotId The id of the spot to report.
	 * @param website The web address of this spot.
	 * @param comment An optional comment.  These always help the eventual spot fixer, I encourage you to provide comments.
	 * @return A ProblemReport object to send to Gowalla.
	 */		
	public static ProblemReport reportWebsite(final int spotId, final String website, final String comment) {		
		if(spotId == 0) {
			throw new IllegalArgumentException("Provide a correct spot");
		}
		if(website == null) {
			throw new IllegalArgumentException("Provide website");
		}
		String message = null;
		if(comment == null) {
			message = String.format("Needs website address: %s", website);
		} else {
			message = String.format("Needs website address: %s [%s]", website, comment);
		}
		return new ProblemReport(ProblemReport.Type.INACCURATE_INFORMATION, spotId, message);
	}
}
